package raft

//
// this is an outline of the API that raft must expose to
// the service (or tester). see comments below for
// each of these functions for more details.
//
// rf = Make(...)
//   create a new Raft server.
// rf.Start(command interface{}) (index, term, isleader)
//   start agreement on a new log entry
// rf.GetState() (term, isLeader)
//   ask a Raft for its current term, and whether it thinks it is leader
// ApplyMsg
//   each time a new entry is committed to the log, each Raft peer
//   should send an ApplyMsg to the service (or tester)
//   in the same server.
//

import (
	"crypto/rand"
	"log"
	"math/big"
	//	"bytes"
	"sync"
	"sync/atomic"
	"time"

	//	"6.824/labgob"
	"6.824/labrpc"
)

//
//as each Raft peer becomes aware that successive log entries are
//committed, the peer should send an ApplyMsg to the service (or
//tester) on the same server, via the applyCh passed to Make(). set
//CommandValid to true to indicate that the ApplyMsg contains a newly
//committed log entry.
// 当每个Raft节点意识到连续的日志记录被提交时，
// 节点应该通过传递给Make()的applyCh向同一服务器上的服务(或测试者)发送一个ApplyMsg。
// 将CommandValid设置为true表示ApplyMsg包含一个新提交的日志条目。
//
//in part 2D you'll want to send other kinds of messages (e.g.,
//snapshots) on the applyCh, but set CommandValid to false for these
//other uses.
//

type ApplyMsg struct {
	CommandValid bool
	Command      interface{}
	CommandIndex int

	// For 2D:
	SnapshotValid bool
	Snapshot      []byte
	SnapshotTerm  int
	SnapshotIndex int
}

// Raft
// A Go object implementing a single Raft peer.
//
type Raft struct {
	mu        sync.Mutex          // Lock to protect shared access to this peer's state
	peers     []*labrpc.ClientEnd // RPC end points of all peers
	persister *Persister          // Object to hold this peer's persisted state
	me        int                 // this peer's index into peers[]
	dead      int32               // set by Kill()
	applyCh   chan ApplyMsg       // 对于每个Raft peer在更新commitIndex提交某个日志时都通过channel发送消息到上层状态机进行应用

	// Your data here (2A, 2B, 2C).
	// Look at the paper's Figure 2 for a description of what
	// state a Raft server must maintain.

	// 更新时应该持久化在persister中
	// Persistent state on all servers
	currentTerm int        // 当前任期
	votedFor    int        // 当前任期投票给了谁
	log         []LogEntry // 保存的日志记录，每个日志记录中包含状态机的命令以及纪录被接收时的leader任期（初始为1）

	// Volatile state on all servers
	commitIndex int // 已知被提交的日志记录最大索引（初始为0，单调增长）
	lastApplied int // 被应用于状态机的日志记录的最大索引（初始为0，单调增长）

	// Volatile state on leaders
	nextIndex  []int // 对于每一个服务，要发送给那个服务器的下一条日志记录的索引（初始为leader的最后一条日志索引+1）
	matchIndex []int // 对于每一个服务，已知被复制在服务上的最高日志记录的索引

	status             string    // 当前Raft peer的状态：leader / follower / candidate
	lastHeartBeatTime  time.Time // 最后一次心跳时间，交给ticker()参考，每次收到有效心跳或请求投票则更新，超过等待时间就开始选举
	lastCandidateTime  time.Time // 上一次选举开始时间
	heartBeatCycle     int       // 心跳周期
	timeOut            int       // 超时时间，在 开始 / 心跳超时 / 选举超时 的情况时更新该值
	leader             int       // 当前leader
	currentVote        int       // 当前获得选票数量
	currentRequestVote int       // 当前结束的选票请求数量

	lastAppendStart       time.Time // 最近发送心跳的时间
	currentAppendReplyNum int       // 当前心跳的返回数量如果心跳响应数量不超过1/2则认为集群不健康直接返回Start()，不健康不会提交不会应用
	healthy               bool      // 集群健康状态
}

// LogEntry 每个日志记录中包含状态机的命令以及纪录被接收时的leader任期
type LogEntry struct {
	Term    int
	Command interface{}
	Index   int
}

// GetState return currentTerm and whether this server
// believes it is the leader.
func (rf *Raft) GetState() (int, bool) {

	var term int
	var isleader bool
	// Your code here (2A).

	rf.mu.Lock()
	term = rf.currentTerm
	isleader = rf.status == "leader"
	rf.mu.Unlock()
	return term, isleader
}

//
// save Raft's persistent state to stable storage,
// where it can later be retrieved after a crash and restart.
// see paper's Figure 2 for a description of what should be persistent.
//
func (rf *Raft) persist() {
	// Your code here (2C).
	// Example:
	// w := new(bytes.Buffer)
	// e := labgob.NewEncoder(w)
	// e.Encode(rf.xxx)
	// e.Encode(rf.yyy)
	// data := w.Bytes()
	// rf.persister.SaveRaftState(data)
}

//
// restore previously persisted state.
//
func (rf *Raft) readPersist(data []byte) {
	if data == nil || len(data) < 1 { // bootstrap without any state?
		return
	}
	// Your code here (2C).
	// Example:
	// r := bytes.NewBuffer(data)
	// d := labgob.NewDecoder(r)
	// var xxx
	// var yyy
	// if d.Decode(&xxx) != nil ||
	//    d.Decode(&yyy) != nil {
	//   error...
	// } else {
	//   rf.xxx = xxx
	//   rf.yyy = yyy
	// }
}

// CondInstallSnapshot
// A service wants to switch to snapshot.  Only do so if Raft hasn't
// have more recent info since it communicate the snapshot on applyCh.
//
func (rf *Raft) CondInstallSnapshot(lastIncludedTerm int, lastIncludedIndex int, snapshot []byte) bool {

	// Your code here (2D).

	return true
}

// Snapshot the service says it has created a snapshot that has
// all info up to and including index. this means the
// service no longer needs the log through (and including)
// that index. Raft should now trim its log as much as possible.
func (rf *Raft) Snapshot(index int, snapshot []byte) {
	// Your code here (2D).

}

// RequestVoteArgs
// example RequestVote RPC arguments structure.
// field names must start with capital letters!
//
type RequestVoteArgs struct {
	// Your data here (2A, 2B).

	Term         int // 候选人的任期
	CandidateId  int // 请求选票的候选人Id
	LastLogIndex int // 候选人最后一条日志记录的索引
	LastLogTerm  int // 候选人最后一条日志记录的任期
}

// RequestVoteReply
// example RequestVote RPC reply structure.
// field names must start with capital letters!
//
type RequestVoteReply struct {
	// Your data here (2A).

	Term        int  // 当前任期，候选人用来更新自己
	VoteGranted bool // true意味着候选人得到了选票
}

// RequestVote
// example RequestVote RPC handler.
// 被远程调用的处理方法
//
func (rf *Raft) RequestVote(args *RequestVoteArgs, reply *RequestVoteReply) {
	rf.mu.Lock()
	defer rf.mu.Unlock()
	log.Printf("%v	%v%d term%d收到candidate%d term%d的选票RPC调用并开始处理（选票RPC调用）\n",
		time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, args.CandidateId, args.Term)
	// Your code here (2A, 2B).

	if args.Term > rf.currentTerm {
		rf.currentTerm = args.Term
	}

	//2B限制
	//RPC包含关于候选人日志的信息，如果投票者自己的日志比候选人的日志更最新，那么投票者就拒绝投票。
	//Raft通过比较日志中最后一个记录的索引和任期来确定两个日志中哪一个是最新的。
	//如果日志的最后一个记录具有不同的任期，那么后面那个任期的日志是最新的。
	//如果日志以相同的任期结束，那么较长的日志是最新的。
	lastLogIndex := len(rf.log)
	var lastLogTerm int
	if lastLogIndex > 0 {
		lastLogTerm = rf.log[len(rf.log)-1].Term
	} else {
		lastLogTerm = 0
	}

	if args.LastLogTerm == lastLogTerm {
		//任期一样，比较索引，如果请求的索引小不投票
		if args.LastLogIndex < lastLogIndex {
			log.Printf("%v	candidate%d最后一条日志任期%v等于自己%s%d任期%v，但索引%v小于自己%v，决定不投票（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm,
				args.LastLogIndex, lastLogIndex)

			reply.Term = rf.currentTerm
			reply.VoteGranted = false
			return
		}
	} else if args.LastLogTerm < lastLogTerm {
		// 最后一条日志任期不一样，如果它的小则不投票
		log.Printf("%v	candidate%d最后一条日志任期%v小于自己%s%d最后一条日志任期%v，决定不投票（选票RPC调用）\n",
			time.Now().UnixNano()/1e6, args.CandidateId, args.LastLogTerm, rf.status, rf.me, lastLogTerm)

		reply.Term = rf.currentTerm
		reply.VoteGranted = false
		return
	}

	//对于一个follower而言它所处的任期就是其他收到大于自己任期的时候投票或者心跳而更新过来，投票时已经投票，心跳则未投票（未投票的小于一半）
	//follower直接投票，candidate、leader需要转换状态
	if rf.status == "follower" {
		//候选者任期请求大于自己任期可投票,否则直接拒绝并返回自己的任期
		if args.Term > rf.currentTerm {
			log.Printf("%v	candidate%d更新%v%d的最近心跳时间（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, rf.status, rf.me)
			rf.lastHeartBeatTime = time.Now()

			log.Printf("%v	candidate%d任期%v大于自己%s%d任期%v,决定投票（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm)
			//大于自己的话则更新自己的任期并把票投出去
			//rf.currentTerm = args.Term
			rf.votedFor = args.CandidateId

			reply.VoteGranted = true
			reply.Term = rf.currentTerm
		} else if args.Term == rf.currentTerm {
			if rf.votedFor == -1 {
				log.Printf("%v	candidate%d更新%v%d的最近心跳时间（选票RPC调用）\n",
					time.Now().UnixNano()/1e6, args.CandidateId, rf.status, rf.me)
				rf.lastHeartBeatTime = time.Now()

				log.Printf("%v	candidate%d任期%v等于自己%s%d任期%v，自己还未投票,决定投票（选票RPC调用）\n",
					time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm)
				//rf.currentTerm = args.Term
				rf.votedFor = args.CandidateId

				reply.VoteGranted = true
				reply.Term = rf.currentTerm
			} else {
				log.Printf("%v	candidate%d任期%v等于自己%s%d任期%v，自己已投票,决定不投票（选票RPC调用）\n",
					time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm)

				reply.Term = rf.currentTerm
				reply.VoteGranted = false
			}
		} else {
			log.Printf("%v	candidate%d任期%v小于自己%s%d任期%v，决定不投票（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm)

			reply.Term = rf.currentTerm
			reply.VoteGranted = false
		}
	} else if rf.status == "candidate" {
		//如果自己为候选者则当前任期票已经给自己，自己只会投给大于自己任期
		if args.Term <= rf.currentTerm {
			log.Printf("%v	candidate%d任期%v小于等于自己%s%d任期%v,决定不投票（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm)

			reply.Term = rf.currentTerm
			reply.VoteGranted = false
		} else {
			log.Printf("%v	candidate%d更新%v%d的最近心跳时间（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, rf.status, rf.me)
			rf.lastHeartBeatTime = time.Now()

			log.Printf("%v	candidate%d任期%v大于自己%s%d任期%v，决定投票（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm)

			rf.status = "follower"
			rf.votedFor = args.CandidateId
			//rf.currentTerm = args.Term

			reply.Term = rf.currentTerm
			reply.VoteGranted = true
		}
	} else if rf.status == "leader" {
		if args.Term <= rf.currentTerm {
			log.Printf("%v	candidate%d任期%v小于自己%s%d任期%v，决定不投票（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm)

			reply.Term = rf.currentTerm
			reply.VoteGranted = false
		} else {
			log.Printf("%v	candidate%d更新%v%d的最近心跳时间（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, rf.status, rf.me)
			rf.lastHeartBeatTime = time.Now()

			log.Printf("%v	candidate%d任期%v大于自己%s%d任期%v,决定投票（选票RPC调用）\n",
				time.Now().UnixNano()/1e6, args.CandidateId, args.Term, rf.status, rf.me, rf.currentTerm)
			rf.status = "follower"
			rf.votedFor = args.CandidateId
			//rf.currentTerm = args.Term

			reply.Term = rf.currentTerm
			reply.VoteGranted = true
		}
	}

}

//
// example code to send a RequestVote RPC to a server.
// server is the index of the target server in rf.peers[].
// expects RPC arguments in args.
// fills in *reply with RPC reply, so caller should
// pass &reply.
// the types of the args and reply passed to Call() must be
// the same as the types of the arguments declared in the
// handler function (including whether they are pointers).
//
// The labrpc package simulates a lossy network, in which servers
// may be unreachable, and in which requests and replies may be lost.
// Call() sends a request and waits for a reply. If a reply arrives
// within a timeout interval, Call() returns true; otherwise
// Call() returns false. Thus Call() may not return for a while.
// A false return can be caused by a dead server, a live server that
// can't be reached, a lost request, or a lost reply.
//
// Call() is guaranteed to return (perhaps after a delay) *except* if the
// handler function on the server side does not return.  Thus there
// is no need to implement your own timeouts around Call().
//
// look at the comments in ../labrpc/labrpc.go for more details.
//
// if you're having trouble getting RPC to work, check that you've
// capitalized all field names in structs passed over RPC, and
// that the caller passes the address of the reply struct with &, not
// the struct itself.
//
func (rf *Raft) sendRequestVote(server int, args *RequestVoteArgs, reply *RequestVoteReply) bool {
	// 记录请求前状态
	rf.mu.Lock()
	startTime := rf.lastCandidateTime
	timeOut := rf.timeOut
	rf.mu.Unlock()

	log.Printf("%v	%v%d任期%v向peer%d开始发送请求选票RPC\n",
		time.Now().UnixNano()/1e6, rf.status, args.CandidateId, rf.currentTerm, server)
	// 发送请求
	ok := rf.peers[server].Call("Raft.RequestVote", args, reply)

	if !ok {
		log.Printf("%v	%v%v任期%v发送选票请求给peer%v无响应（投票RPC调用失败）\n",
			time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, server)
		return ok
	}

	rf.mu.Lock()
	defer rf.mu.Unlock()
	// 可能已经超时
	if time.Now().UnixNano()/1e6-startTime.UnixNano()/1e6 >= int64(timeOut-1) || rf.status != "candidate" {
		return ok
	}
	// 如果没超时，且响应任期小于等于自己判断加票，如果任期大于则将自身改为follower
	if reply.Term <= rf.currentTerm {
		log.Printf("%v	%v%d请求选票结果任期大于等于peer%d查看投票结果\n",
			time.Now().UnixNano()/1e6, rf.status, args.CandidateId, rf.me)
		if reply.VoteGranted {
			log.Printf("%v	%v%d请求选票结果任期大于等于peer%d成功获得选票，当前票数%d\n",
				time.Now().UnixNano()/1e6, rf.status, args.CandidateId, rf.me, rf.currentVote+1)
			rf.currentVote++
		}
	} else {
		log.Printf("%v	%v%d请求选票结果任期小于peer%d自身转为follower\n",
			time.Now().UnixNano()/1e6, rf.status, args.CandidateId, rf.me)
		rf.status = "follower"
		rf.currentTerm = reply.Term
		rf.votedFor = -1
	}
	rf.currentRequestVote++
	log.Printf("%v	candidate%d向peer%d请求选票完成，当前状态为%v，拥有票数%d \n",
		time.Now().UnixNano()/1e6, args.CandidateId, server, rf.status, rf.currentVote)
	return ok
}

//并发请求选票
func (rf *Raft) getRequestVotes() {
	log.Printf("%v	%d开始并发征求选票，当前任期为%v\n",
		time.Now().UnixNano()/1e6, rf.me, rf.currentTerm)

	for i, _ := range rf.peers {
		// 排除自己
		if i != rf.me && rf.status == "candidate" {
			rf.mu.Lock()
			log.Printf("%v	candidate%d向peer%d发送请求选票RPC\n",
				time.Now().UnixNano()/1e6, rf.me, i)
			args := RequestVoteArgs{}
			args.Term = rf.currentTerm
			args.CandidateId = rf.me

			if len(rf.log) > 0 {
				args.LastLogIndex = len(rf.log)
				args.LastLogTerm = rf.log[len(rf.log)-1].Term
			} else {
				args.LastLogIndex = 0
				args.LastLogTerm = 0
			}

			reply := RequestVoteReply{}
			rf.mu.Unlock()

			go rf.sendRequestVote(i, &args, &reply)
		}
	}
	// 开启所有线程后更新超时时间
	//genTimeOut, _ := rand.Int(rand.Reader, big.NewInt(200))
	//rf.timeOut = int(300 + genTimeOut.Int64())
	//log.Printf("%v	candidate%d更新超时时间为%dms",
	//	time.Now().UnixNano()/1e6, rf.me, rf.timeOut)
}

type AppendEntriesArgs struct {
	Term         int        // leader的任期
	LeaderId     int        // leader的Id，其他follower可以重定向到leader
	PreLogIndex  int        // 紧接在新日志记录之前的日志记录索引
	PreLogTerm   int        // preLogIndex记录的任期
	LeaderCommit int        // leader的commitIndex
	Entries      []LogEntry // 要记录的日志记录（空心跳；为了效率可能发送超过一个记录）
}

type AppendEntriesReply struct {
	Term       int  // 当前任期，为了leader可以更新自己
	Success    bool // 如果跟随着包含记录匹配preLogIndex和preLogTerm则返回true
	MatchIndex int  // 当前follower的lastLogIndex

	ConflictTerm             int // 冲突记录的所处任期
	FirstIndexInConflictTerm int // 冲突记录所处任期的第一个记录索引，如果不包含该索引则返回-1表明follower没有该任期的索引，如果不为-1则比较是否冲突
}

func updateCommitIndex(args *AppendEntriesArgs, rf *Raft) {
	if args.LeaderCommit > rf.commitIndex {
		if args.LeaderCommit <= len(rf.log) {
			log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v lastLogTerm%v，设置commitIndex = leaderCommit%v\n",
				time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log), rf.log[len(rf.log)-1].Term, args.LeaderCommit)

			rf.commitIndex = args.LeaderCommit
		} else {
			log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v lastLogTerm%v，设置commitIndex = 最后一条日志索引%v\n",
				time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log), rf.log[len(rf.log)-1].Term, len(rf.log))

			rf.commitIndex = len(rf.log)
		}
	}
}

// AppendEntries 被远程调用的处理方法
func (rf *Raft) AppendEntries(args *AppendEntriesArgs, reply *AppendEntriesReply) {
	rf.mu.Lock()
	defer rf.mu.Unlock()
	log.Printf("%v	%v%d任期%d收到心跳来自leader%d任期%d preLogTerm%v preLogIndex%v 自己logs%v（追加日志心跳调用） \n",
		time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, args.LeaderId, args.Term, args.PreLogTerm, args.PreLogIndex, rf.log)

	// 如果follower可能直接添加，其他可能更新自己状态
	if rf.status == "follower" {
		if args.Term >= rf.currentTerm {
			log.Printf("%v	%v%d更新%v%d的最近心跳时间（追加日志心跳调用）\n",
				time.Now().UnixNano()/1e6, "leader", args.LeaderId, rf.status, rf.me)
			rf.lastHeartBeatTime = time.Now()

			if args.Term > rf.currentTerm {
				log.Printf("%v	leader%d任期%v大于自己%s%d任期%v，更新所处任期（追加日志心跳调用）\n",
					time.Now().UnixNano()/1e6, args.LeaderId, args.Term, rf.status, rf.me, rf.currentTerm)
				rf.votedFor = -1 // leader新任期自己还没投票自己就上来了
			} else {
				log.Printf("%v	leader%d任期%v等于自己%s%d任期%v，继续保持所处任期（追加日志心跳调用）\n",
					time.Now().UnixNano()/1e6, args.LeaderId, args.Term, rf.status, rf.me, rf.currentTerm)
			}

			rf.currentTerm = args.Term
			rf.leader = args.LeaderId

			//  使用entry数量表示是否含有追加日志，prelog正常表示
			//  如果不管是不是空心跳都正常prelogIndex则如果匹配prelogIndex且含entry则追加，如果匹配不含则不追加，如果不匹配则返回失败
			// 2B 根据日志条件设置响应
			// 首先是有没有preLogIndex 没有返回false
			// 其次有判空、冲突
			if 0 <= args.PreLogIndex && args.PreLogIndex <= len(rf.log) {
				// 确定含有prelog，0<=log
				if len(rf.log) == 0 || args.PreLogIndex == 0 {
					if len(args.Entries) > 0 {
						log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v，自身没有或从头添加，日志追加成功\n",
							time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log))

						rf.log = args.Entries
					} else {
						log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v，空心跳，日志不追加\n",
							time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log))

						rf.log = args.Entries
					}

					// 2B
					// 如果追加成功才执行如果leaderCommit > commitIndex，设置commitIndex = min(leaderCommit，最后一个新记录的索引)
					updateCommitIndex(args, rf)

					reply.Success = true
				} else if rf.log[args.PreLogIndex-1].Term == args.PreLogTerm {
					if args.PreLogIndex == len(rf.log) {
						// 末尾拼接
						log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v lastLogTerm%v，匹配preLog成功，日志追加成功\n",
							time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log), rf.log[len(rf.log)-1].Term)

						rf.log = append(rf.log, args.Entries...)
					} else {
						// 中间覆盖
						log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v lastLogTerm%v，匹配preLog成功，日志覆盖追加成功\n",
							time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log), rf.log[len(rf.log)-1].Term)

						rf.log = rf.log[:args.PreLogIndex]
						rf.log = append(rf.log, args.Entries...)
					}
					updateCommitIndex(args, rf)

					reply.Success = true
				} else {
					// 冲突
					log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v lastLogTerm%v，preLog任期%v冲突，日志追加失败\n",
						time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log), rf.log[len(rf.log)-1].Term, rf.log[args.PreLogIndex-1].Term)

					reply.FirstIndexInConflictTerm = -1 // leader看见-1就直接从preLogTerm前一个任期最后一个索引开始
					reply.ConflictTerm = args.PreLogTerm
					reply.Success = false
				}
			} else {
				if len(rf.log) > 0 {
					log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v lastLogTerm%v，不含preLog，日志追加失败\n",
						time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log), rf.log[len(rf.log)-1].Term)
				} else {
					log.Printf("%v	leader%d任期%vpreLogIndex%v preLogTerm%v，自己%s%d任期%v lastLogIndex%v lastLogTerm%v，不含preLog，日志追加失败\n",
						time.Now().UnixNano()/1e6, args.LeaderId, args.Term, args.PreLogIndex, args.PreLogTerm, rf.status, rf.me, rf.currentTerm, len(rf.log), 0)
				}

				//firstIndexInConflictTerm := 1
				////找到该任期的第一个日志索引
				//for i := len(rf.log)-1; i >= 0; i++ {
				//	if rf.log[i].Term < args.PreLogTerm {
				//		firstIndexInConflictTerm = rf.log[i].Index + 1
				//		break
				//	}
				//}
				//
				//// 如果包含任期找第一个
				//if rf.log[firstIndexInConflictTerm-1].Term == args.PreLogTerm {
				//	reply.FirstIndexInConflictTerm = firstIndexInConflictTerm
				//} else {
				//	//如果不包含该索引所在任期则返回-1
				//	reply.FirstIndexInConflictTerm = -1 // leader看见-1就直接从preLogTerm前一个任期最后一个索引开始
				//}
				reply.FirstIndexInConflictTerm = -1 // leader看见-1就直接从preLogTerm前一个任期最后一个索引开始
				reply.ConflictTerm = args.PreLogTerm
				reply.Success = false
			}

			reply.MatchIndex = len(rf.log)
			reply.Term = args.Term
			// 追加结束
		} else {
			log.Printf("%v	leader%d任期%v小于自己%s%d任期%v，设置响应为失败（追加日志心跳调用）\n",
				time.Now().UnixNano()/1e6, args.LeaderId, args.Term, rf.status, rf.me, rf.currentTerm)

			reply.Term = rf.currentTerm
			reply.Success = false
		}
	} else if rf.status == "candidate" {
		//收到大于等于自己的任期的转为follower
		if args.Term >= rf.currentTerm {
			log.Printf("%v	%v%d更新%v%d的最近心跳时间（追加日志心跳调用）\n",
				time.Now().UnixNano()/1e6, "leader", args.LeaderId, rf.status, rf.me)
			rf.lastHeartBeatTime = time.Now()

			log.Printf("%v	leader%d任期%v大于自己%s%d任期%v，更新自身为follower（追加日志心跳调用）\n",
				time.Now().UnixNano()/1e6, args.LeaderId, args.Term, rf.status, rf.me, rf.currentTerm)
			rf.status = "follower"
			rf.currentTerm = args.Term
			rf.leader = args.LeaderId

			reply.Term = rf.currentTerm
		} else {
			log.Printf("%v	leader%d任期%v小于自己%s%d任期%v，继续进行选举（追加日志心跳调用）\n",
				time.Now().UnixNano()/1e6, args.LeaderId, args.Term, rf.status, rf.me, rf.currentTerm)

			reply.Term = rf.currentTerm
		}
	} else if rf.status == "leader" {
		//收到大于自己的任期的转为follower
		if args.Term > rf.currentTerm {
			log.Printf("%v	%v%d更新%v%d的最近心跳时间（增加日志心跳调用）\n",
				time.Now().UnixNano()/1e6, "leader", args.LeaderId, rf.status, rf.me)
			rf.lastHeartBeatTime = time.Now()

			log.Printf("%v	leader%d任期%v大于自己%s%d任期%v，更新自身为follower（追加日志心跳调用）\n",
				time.Now().UnixNano()/1e6, args.LeaderId, args.Term, rf.status, rf.me, rf.currentTerm)
			rf.status = "follower"
			rf.currentTerm = args.Term
			rf.leader = args.LeaderId

			reply.Term = rf.currentTerm
		} else {
			log.Printf("%v	leader%d任期%v小于等于自己%s%d任期%v，不改变自身（追加日志心跳调用）\n",
				time.Now().UnixNano()/1e6, args.LeaderId, args.Term, rf.status, rf.me, rf.currentTerm)
			reply.Term = rf.currentTerm
		}
	}
}

//sendAppendEntries 用于心跳、日志复制重复尝试功能
func (rf *Raft) sendAppendEntries(server int, args *AppendEntriesArgs, reply *AppendEntriesReply) bool {

	rf.mu.Lock()
	if len(rf.log) > 0 {
		log.Printf("%v	%v%v任期%v开始发送心跳给peer%v nextIndex%v matchIndex%v,最后日志term%v index%v\n",
			time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, server,
			rf.nextIndex[server], rf.matchIndex[server], rf.log[len(rf.log)-1].Term, len(rf.log))
	} else {
		log.Printf("%v	%v%v任期%v开始发送心跳给peer%v nextIndex%v matchIndex%v，无日志\n",
			time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, server,
			rf.nextIndex[server], rf.matchIndex[server])
	}
	args.Term = rf.currentTerm
	startTime := rf.lastAppendStart // 此次心跳开始时间
	rf.matchIndex[rf.me] = len(rf.log)
	rf.mu.Unlock()

	ok := rf.peers[server].Call("Raft.AppendEntries", args, reply)

	if !ok {
		log.Printf("%v	%v%v任期%v发送心跳给peer%v无响应（追加日志心跳RPC调用失败）\n",
			time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, server)
		return ok
	} else {
		//如果此次心跳在该轮返回则增加成功数量，下次心跳前检查
		if time.Since(startTime).Milliseconds() < 98 {
			rf.mu.Lock()
			rf.currentAppendReplyNum++
			rf.mu.Unlock()
		}
	}

	rf.mu.Lock()
	// 对于leader而言处理返回比自己大的任期，自己变为follower
	if rf.status == "leader" && reply.Term > rf.currentTerm {
		log.Printf("%v	%v%d追加日志心跳peer%v响应任期%v大于自己任期%v，改变自己状态为follower，更新心跳时间\n",
			time.Now().UnixNano()/1e6, rf.status, rf.me, server, reply.Term, rf.currentTerm)
		rf.lastHeartBeatTime = time.Now()
		rf.status = "follower"
		rf.votedFor = -1
		rf.currentTerm = reply.Term
	} else {
		// 否则根据返回的情况调整相应的nextIndex、matchIndex

		if reply.Success {
			//如果匹配成功并且追加日志了才更新，如果仅匹配成功无日志不更新
			if len(args.Entries) > 0 {
				rf.nextIndex[server] = reply.MatchIndex + 1
			}
			rf.matchIndex[server] = reply.MatchIndex

			log.Printf("%v	%v%v任期%v追加日志心跳给peer%v成功更新此peer的nextIndex为%v matchIndex为%v\n",
				time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, server,
				rf.nextIndex[server], rf.matchIndex[server])
		} else if !reply.Success {
			//如果匹配不成功则减少nextIndex
			if rf.nextIndex[server] > 1 {
				log.Printf("%v	%v%v任期%v追加日志心跳给peer%v失败，当前leader的log%v peer的nextIndex为%v matchIndex为%v\n",
					time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, server,
					rf.log, rf.nextIndex[server], rf.matchIndex[server])
				// 跳过冲突任期
				oldNextIndex := rf.nextIndex[server]
				for i := len(rf.log) - 1; i >= 0; i-- {
					if rf.log[i].Term < reply.ConflictTerm {
						rf.nextIndex[server] = rf.log[i].Index
						break
					}
				}
				if oldNextIndex == rf.nextIndex[server] {
					rf.nextIndex[server] = 1
				}

				//rf.nextIndex[server]--
				rf.matchIndex[server] = reply.MatchIndex

				log.Printf("%v	%v%v任期%v追加日志心跳给peer%v失败，更新此peer的nextIndex为%v matchIndex为%v\n",
					time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, server,
					rf.nextIndex[server], rf.matchIndex[server])
			}
		}
	}
	rf.mu.Unlock()
	return ok
}

//sendAppendEntries 用于日志复制与心跳功能
func (rf *Raft) sendAllAppendEntries() {

	//每heartBeatCycle ms并发发送
	for rf.status == "leader" && rf.killed() == false {

		log.Printf("%v	%v%d任期%v开始发送心跳，当前commitIndex%v appliedIndex%v matchIndex%v nextIndex%v lastLogIndex%v logs%v\n",
			time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, rf.commitIndex, rf.lastApplied, rf.matchIndex, rf.nextIndex, len(rf.log), rf.log)

		rf.mu.Lock()
		if rf.currentAppendReplyNum < len(rf.peers)/2+1 {
			log.Printf("%v	%v%d任期%v上轮心跳成功数量%v过少，集群不健康\n",
				time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, rf.currentAppendReplyNum)
			rf.healthy = false
		} else {
			if !rf.healthy {
				log.Printf("%v	%v%d任期%v上轮心跳成功数量%v，集群恢复健康\n",
					time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, rf.currentAppendReplyNum)
			} else {
				log.Printf("%v	%v%d任期%v上轮心跳成功数量%v，集群健康\n",
					time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, rf.currentAppendReplyNum)
			}
			rf.healthy = true
		}
		rf.currentAppendReplyNum = 1
		rf.lastAppendStart = time.Now()
		rf.mu.Unlock()

		for i, _ := range rf.peers {
			//排除自己
			if i != rf.me && rf.status == "leader" {
				rf.mu.Lock()
				if len(rf.log) > 0 {
					log.Printf("%v	%v%d任期%v发送追加日志心跳给peer%d，最后日志term%v index%v（追加日志心跳）\n",
						time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, i,
						rf.log[len(rf.log)-1].Term, rf.log[len(rf.log)-1].Index)
				} else {
					log.Printf("%v	%v%d任期%v发送追加日志心跳给peer%d，无日志（追加日志心跳）\n",
						time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, i)
				}

				args := AppendEntriesArgs{}
				args.LeaderId = rf.me
				args.Term = rf.currentTerm
				args.LeaderCommit = rf.commitIndex

				// 使用entry数量表示是否含有追加日志，prelog正常表示
				// 如果有日志就按实际preLog填
				if len(rf.log) > 0 {
					// index与数组下标的关系 下标0的index为1，nextIndex最小为1，当大于1时找next-1的索引
					if rf.nextIndex[i] > 1 {
						nextIndex := rf.nextIndex[i]
						args.PreLogTerm = rf.log[nextIndex-2].Term
						args.PreLogIndex = rf.log[nextIndex-2].Index // = nextIndex-1
						// 最后一个日志索引≥follower的nextIndex: 发送日志项从nextIndex开始的AppendEntries RPC
						if len(rf.log) >= rf.nextIndex[i] {
							args.Entries = rf.log[nextIndex-1:]
						}
					} else {
						// if rf.nextIndex[i] == 1
						args.PreLogTerm = 0
						args.PreLogIndex = 0
						if len(rf.log) >= rf.nextIndex[i] {
							args.Entries = rf.log[0:] // 如果nextIndex为1则从发送索引1开始到最后，即数组下标0到最后
						}
					}
				} else {
					// 如果没有日志，nextIndex为1，preLogIndex就是0
					args.PreLogTerm = 0
					args.PreLogIndex = 0
				}

				reply := AppendEntriesReply{}
				rf.mu.Unlock()
				go rf.sendAppendEntries(i, &args, &reply)
			}
		}
		time.Sleep(time.Millisecond * 100)
	}
}

// Start
//the service using Raft (e.g. a k/v server) wants to start
//agreement on the next command to be appended to Raft's log. if this
//server isn't the leader, returns false. otherwise start the
//agreement and return immediately. there is no guarantee that this
//command will ever be committed to the Raft log, since the leader
//may fail or lose an election. even if the Raft instance has been killed,
//this function should return gracefully.
//
//使用Raft的服务(例如一个k/v服务器)想要开始共识的下一个命令被追加到Raft的日志。
//如果这个服务器不是leader，返回false。 否则启动协议并立即返回。
//由于领导人可能会崩溃或输掉一场选举，因此无法保证这个命令将会被写入Raft日志。
//即使Raft实例已经被杀死，这个函数也应该优雅地返回。
//
// the first return value is the index that the command will appear at
// if it's ever committed. the second return value is the current
// term. the third return value is true if this server believes it is
// the leader.
//
// isleader: false if this server isn't the leader, client should try another
// term: currentTerm, to help caller detect if leader is later demoted
// index: log entry to watch to see if the command was committed
//

func (rf *Raft) Start(command interface{}) (int, int, bool) {
	// Your code here (2B).
	rf.mu.Lock()
	index := len(rf.log) + 1
	term := rf.currentTerm
	isLeader := rf.status == "leader"
	if !isLeader {
		rf.mu.Unlock()
		log.Printf("%v	%v%v收到command%v，Index%v，不是leader返回false\n",
			time.Now().UnixNano()/1e6, rf.status, rf.me, command, index)
		return index, term, isLeader
	}

	// 保存日志到leader并开始日志复制
	entry := LogEntry{
		Term:    term,
		Command: command,
		Index:   index,
	}
	rf.log = append(rf.log, entry)

	// 还需要更新自己的matchIndex
	rf.matchIndex[rf.me] = len(rf.log)

	log.Printf("%v	%v%d任期%v收到command%v发送追加日志心跳，该日志term%v index%v（立即追加日志）\n",
		time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, command, term, index)
	rf.mu.Unlock()

	for index > rf.commitIndex && rf.status == "leader" {
		time.Sleep(time.Millisecond)

		if !rf.healthy {
			log.Printf("%v	%v%v收到command%v，集群不健康，响应数量不超过1/2无法处理请求,该日志term%v index%v\n",
				time.Now().UnixNano()/1e6, rf.status, rf.me, command, term, index)
			return index, term, isLeader
		}

	}

	//rf.mu.Lock()
	//defer rf.mu.Unlock()
	//if rf.status == "leader" || index <= rf.lastApplied {
	//	log.Printf("%v	%v%d任期%v已应用command%v（返回客户端）\n",
	//		time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, command)
	//	return index, term, true
	//} else {
	//	log.Printf("%v	%v%d任期%v出现了更大的candidate自身变为follower，不应用command%v（返回客户端）\n",
	//		time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, command)
	//	return index, term, false
	//}
	//如果有candidate打断
	return index, term, isLeader
}

// Kill
// the tester doesn't halt goroutines created by Raft after each test,
// but it does call the Kill() method. your code can use killed() to
// check whether Kill() has been called. the use of atomic avoids the
// need for a lock.
//
// the issue is that long-running goroutines use memory and may chew
// up CPU time, perhaps causing later tests to fail and generating
// confusing debug output. any goroutine with a long-running loop
// should call killed() to check whether it should stop.
//
func (rf *Raft) Kill() {
	atomic.StoreInt32(&rf.dead, 1)
	// Your code here, if desired.
	log.Printf("%v	%v%v被测试器kill\n",
		time.Now().UnixNano()/1e6, rf.status, rf.me)
}

func (rf *Raft) killed() bool {
	z := atomic.LoadInt32(&rf.dead)
	return z == 1
}

func upgradeCommitIndex(rf *Raft) {
	N := len(rf.log)
	if N > rf.commitIndex && rf.status == "leader" {
		rf.mu.Lock()
		nums := 0
		for _, index := range rf.matchIndex {
			if index >= N {
				nums++
			}
		}
		//if nums >= len(rf.peers)/2+1 && rf.log[N-1].Term == rf.currentTerm
		//Raft从不通过计算副本来提交以前的日志记录。
		//只有来自leader当前任期的日志记录是通过计数副本提交的;
		//一旦来自当前任期的记录以这种方式提交，那么由于日志匹配属性，所有之前的记录都将间接提交。
		// 如果这个N虽然数量够但任期不匹配则丢弃然后在心跳中让follower与自己保持一致
		if nums >= len(rf.peers)/2+1 && rf.log[N-1].Term == rf.currentTerm {
			log.Printf("%v	leader%d任期%v，数量足够且是当前任期更新commitIndex为%v\n",
				time.Now().UnixNano()/1e6, rf.me, rf.currentTerm, N)

			rf.commitIndex = N
		} else {
			log.Printf("%v	leader%d任期%v，由于N数量不足未更新commitIndex为%v\n",
				time.Now().UnixNano()/1e6, rf.me, rf.currentTerm, N)
		}
		rf.mu.Unlock()
	}
}

// The ticker go routine starts a new election if this peer hasn't received
// heartsbeats recently.
func (rf *Raft) ticker() {
	for rf.killed() == false {
		// Your code here to check if a leader election should
		// be started and to randomize sleeping time using
		// time.Sleep().

		//在一个goroutine中，自己初始为follower
		time.Sleep(time.Millisecond * 1)

		rf.mu.Lock()
		status := rf.status
		rf.mu.Unlock()

		// 如果自己是leader除非处理心跳返回时遇到比自己大的否则不改变状态
		if status == "leader" {
			//  如果存在一个N，使得N > commitIndex，大部分matchIndex[i]≥N,并且log[N].term == currentTerm则set commitIndex = N
			if len(rf.log) > 0 {
				upgradeCommitIndex(rf)
			}
			continue
		}

		//检查lastHeartenBeatTime是否超过等待时间,超过则转为candidate并发起新一轮选举
		if status == "follower" {
			//超过则开始选举，切换follower为candidate
			if time.Now().UnixNano()/1e6-rf.lastHeartBeatTime.UnixNano()/1e6 > int64(rf.timeOut) {
				rf.mu.Lock()
				// 更新状态、任期、选举时间、票数、请求数
				rf.currentTerm++
				log.Printf("%v	%v%v心跳超时启动新一轮选举新任期为%v",
					time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm)

				genTimeOut, _ := rand.Int(rand.Reader, big.NewInt(200))
				rf.timeOut = int(300 + genTimeOut.Int64())
				log.Printf("%v	candidate%d更新超时时间为%dms",
					time.Now().UnixNano()/1e6, rf.me, rf.timeOut)

				rf.status = "candidate"
				rf.lastCandidateTime = time.Now()
				rf.lastHeartBeatTime = time.Now()
				rf.currentRequestVote = 1
				rf.currentVote = 1 // 投自己一票
				rf.votedFor = rf.me
				rf.mu.Unlock()
				//多线程并发请求选票
				go rf.getRequestVotes()
			}
			continue
		}

		//选举时启动sendRequestVote如果timeOut时间内选出leader
		//选举后如果自己时leader则启动发送心跳的goroutine
		//如果收到心跳则切换candidate为follower 在心跳RPC中处理
		if status == "candidate" {
			//如果选举超时没有结果则开启新一轮的选举（选票被瓜分）
			if time.Now().UnixNano()/1e6-rf.lastCandidateTime.UnixNano()/1e6 > int64(rf.timeOut) {
				rf.mu.Lock()
				//log.Printf("%v	candidate%d收到选票%d张\n", time.Now().UnixNano()/1e6, rf.me, rf.currentVote)
				rf.currentTerm++
				log.Printf("%v	选举超时，上次选举时间%v，%v启动新一轮选举新任期为%v\n",
					time.Now().UnixNano()/1e6, rf.lastHeartBeatTime.UnixNano()/1e6, rf.me, rf.currentTerm)

				genTimeOut, _ := rand.Int(rand.Reader, big.NewInt(200))
				rf.timeOut = int(300 + genTimeOut.Int64())
				log.Printf("%v	candidate%d选举等待超时，更新等待时间为%dms",
					time.Now().UnixNano()/1e6, rf.me, rf.timeOut)

				rf.lastCandidateTime = time.Now()
				rf.lastHeartBeatTime = time.Now()
				rf.currentVote = 1
				rf.currentVote = 1 // 自己一票
				rf.votedFor = rf.me
				rf.mu.Unlock()
				//多线程并发选票
				go rf.getRequestVotes()
			} else {
				//否则检查当前选票情况
				//如果有效选举期内得到大多数选票则转换为leader
				if rf.currentVote >= len(rf.peers)/2+1 {
					rf.mu.Lock()
					log.Printf("%v	%v选举为leader任期为%v，开始发送心跳\n",
						time.Now().UnixNano()/1e6, rf.me, rf.currentTerm)
					//变为leader马上开始发送心跳
					rf.status = "leader"
					upgradeCommitIndex(rf) // 检查自身有没有未提交已复制又不是自己任期的日志
					rf.currentAppendReplyNum = len(rf.peers)
					rf.healthy = true

					//2B 新Leader需要的重新初始化的变量
					for i := 0; i < len(rf.peers); i++ {
						// nextIndex
						if len(rf.log) > 0 {
							// 如果自己有日志的话按最后一条日志的index+1
							rf.nextIndex[i] = len(rf.log) + 1
						} else {
							// 如果没有日志的话起始为1，所以下一条要发的index为1
							rf.nextIndex[i] = 1
						}

						// 初始为0根据响应长matchIndex
						rf.matchIndex[i] = 0
					}
					rf.mu.Unlock()
					go rf.sendAllAppendEntries()
					continue
				}
				//todo 如果所有选票请求已响应可以提前结束不必等待超时
			}
			continue
		}
	}
}

// ApplyLog 如果commitIndex > lastApplied:增长lastApplied，将entry[lastApplied]应用到状态机(§5.3)
func (rf *Raft) ApplyLog() {
	for rf.killed() == false {
		time.Sleep(time.Millisecond)
		for rf.commitIndex > rf.lastApplied {
			rf.mu.Lock()
			log.Printf("%v	%v%d任期%v，应用commit日志index%v,command%v到状态机\n",
				time.Now().UnixNano()/1e6, rf.status, rf.me, rf.currentTerm, rf.lastApplied+1, rf.log[rf.lastApplied].Command)

			msg := ApplyMsg{
				CommandValid:  true,
				Command:       rf.log[rf.lastApplied].Command, // 初始0，log中下标0
				CommandIndex:  rf.lastApplied + 1,             // log0中索引为1
				SnapshotValid: false,
				Snapshot:      nil,
				SnapshotTerm:  0,
				SnapshotIndex: 0,
			}
			rf.applyCh <- msg
			rf.lastApplied++
			rf.mu.Unlock()
		}
	}
}

// Make
// the service or tester wants to create a Raft server. the ports
// of all the Raft servers (including this one) are in peers[]. this
// server's port is peers[me]. all the servers' peers[] arrays
// have the same order. persister is a place for this server to
// save its persistent state, and also initially holds the most
// recent saved state, if any. applyCh is a channel on which the
// tester or service expects Raft to send ApplyMsg messages.
// Make() must return quickly, so it should start goroutines
// for any long-running work.
//
func Make(peers []*labrpc.ClientEnd, me int,
	persister *Persister, applyCh chan ApplyMsg) *Raft {
	rf := &Raft{}
	rf.peers = peers
	rf.persister = persister
	rf.me = me
	rf.applyCh = applyCh
	log.Printf("%v	初始化Raft peer%v\n", time.Now().UnixNano()/1e6, me)
	// Your initialization code here (2A, 2B, 2C).
	// 2A
	rf.status = "follower" // 初始都为follower
	rf.currentTerm = 0
	rf.heartBeatCycle = 100
	rf.commitIndex = 0
	rf.lastApplied = 0
	rf.votedFor = -1
	genTimeOut, _ := rand.Int(rand.Reader, big.NewInt(200))
	rf.timeOut = int(300 + genTimeOut.Int64())
	rf.lastHeartBeatTime = time.Now()
	rf.lastCandidateTime = time.Now()
	// 2B
	rf.nextIndex = make([]int, len(peers))
	rf.matchIndex = make([]int, len(peers))

	// initialize from state persisted before a crash
	rf.readPersist(persister.ReadRaftState())

	// start ticker goroutine to start elections
	log.Printf("%v	%v%d启动监测线程\n", time.Now().UnixNano()/1e6, rf.status, rf.me)
	go rf.ticker()

	// 2B
	go rf.ApplyLog()

	log.Printf("%v	%v%d初始化完成\n", time.Now().UnixNano()/1e6, rf.status, rf.me)
	return rf
}
